#include "iap.h"

//IAP跳转至APP
void iap_load_app(u32 appxaddr)
{
  int i;
	iapfun jump2app; 
	
	if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)
	{
    /* never return */
		printf("Check Sucess,Begin Exec App\r\n");
		jump2app=(iapfun)*(vu32*)(appxaddr+4);
		MSR_MSP(*(vu32*)appxaddr);				
		jump2app();								
	}
}

//IAP应用程序启动堆栈设置
void IAP_JumpExec(void)
{
	SCB->VTOR = STMFLASH_APP1_ADDR;
}

//IAP升级程序处理函数
void IAP_RecvFile(IAP_RecvFun FunRecv, u16 byte)
{
	__IO u32 addr = FLASH_APP2_ADDR;
	__IO u32 userinfo = STMFLASH_DATA_ADDR;
	
	u16 ret=0;
	u32 RecvByte = 0;
	
	tpm_sha1_ctx_t ctx;
	
	u8 *buff;//接收缓存
	uint8_t digest[SHA1_DIGEST_LENGTH];//SHA结果储存
	
	if(FunRecv == NULL) return;
	
	buff= mymalloc(SRAMIN, byte);
	tpm_sha1_init(&ctx);
	
	//循环接收文件数据，超时退出
	printf("Begin Recv File:\r\n");
	while(ret = FunRecv(buff, byte, 100), ret)
	{
		//接收错误
		if(ret == INVALIDVAL)
		{
			printf("RECV FAILD,Give Up Recv\r\n");
			break;
		}
		
		SPI_Flash_Write(buff, addr, ret);
		tpm_sha1_update(&ctx, buff, ret);
		RecvByte += ret;
		addr += ret;
		delay_ms(5);
	}
	tpm_sha1_final(&ctx, digest);
	myfree(SRAMIN, buff);
	
	if(ret >= 0)
	{	//完成标志
		ret = 0x5050;
		STMFLASH_Write(userinfo, &ret, 1);
		userinfo += 2;
		
		//写入程序字节数
		ret = (u16)((RecvByte>>16)&0xFFFF);
		STMFLASH_Write(userinfo, &ret, 1);
		userinfo += 2;
		
		ret = (u16)(RecvByte&0xFFFF);
		STMFLASH_Write(userinfo, &ret, 1);
		userinfo += 2;
		
		//写入校验结果
		STMFLASH_Write(userinfo, (u16*)digest, SHA1_DIGEST_LENGTH/2);
		printf("UpData Sucess,SHA:\r\n");
		printsha1(digest);
		
		printf("MCU RESET\r\n");
		Reset_MCU();
	}
}
